﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.ComponentModel.DataAnnotations;
using AnyGrid.Metadata;

namespace AnyGrid.Tests.Metadata
{
    [TestClass]
    public class ExtendedDataAnnotationsModelMetadataProviderTests
    {
        [TestMethod]
        public void AutoGenerateFilter_correctly_mapped()
        {
            Type input = typeof(TestModel);
            var mp = new ExtendedDataAnnotationsModelMetadataProvider();

            var result = mp.GetMetadataForType(null, input);

            var none = result.Properties.Single(p => p.PropertyName == "DoesNotHaveAutoGenerateFilter");
            var withFalse = result.Properties.Single(p => p.PropertyName == "HasAutoGenerateFilterFalse");
            var withTrue = result.Properties.Single(p => p.PropertyName == "HasAutoGenerateFilterTrue");

            Assert.IsFalse(none.AdditionalValues.ContainsKey(AdditionalValuesKeys.AutoGenerateFilter));
            Assert.AreEqual(false, withFalse.AdditionalValues[AdditionalValuesKeys.AutoGenerateFilter]);
            Assert.AreEqual(true, withTrue.AdditionalValues[AdditionalValuesKeys.AutoGenerateFilter]);
        }

        [TestMethod]
        public void GroupName_correctly_mapped()
        {
            Type input = typeof(TestModel);
            var mp = new ExtendedDataAnnotationsModelMetadataProvider();

            var result = mp.GetMetadataForType(null, input);

            var noGroupName = result.Properties.Single(p => p.PropertyName == "DoesNotHaveGroupName");
            var hasGroupName = result.Properties.Single(p => p.PropertyName == "HasGroupName");
            
            Assert.IsFalse(noGroupName.AdditionalValues.ContainsKey(AdditionalValuesKeys.GroupName));
            Assert.AreEqual("Bob", hasGroupName.AdditionalValues[AdditionalValuesKeys.GroupName]);
        }

        [TestMethod]
        public void SortColumn_correctly_mapped()
        {
            Type input = typeof(TestModel);
            var mp = new ExtendedDataAnnotationsModelMetadataProvider();

            var result = mp.GetMetadataForType(null, input);

            Assert.AreEqual("SortMe", result.AdditionalValues[AdditionalValuesKeys.SortColumnName]);
        }

        [TestMethod]
        public void SortDescending_correctly_mapped_when_false()
        {
            Type input = typeof(TestModel);
            var mp = new ExtendedDataAnnotationsModelMetadataProvider();

            var result = mp.GetMetadataForType(null, input);

            Assert.IsFalse(result.AdditionalValues.ContainsKey(AdditionalValuesKeys.SortDescending));
        }

        [TestMethod]
        public void SortDescending_correctly_mapped_when_true()
        {
            Type input = typeof(TestModelSortDescending);
            var mp = new ExtendedDataAnnotationsModelMetadataProvider();

            var result = mp.GetMetadataForType(null, input);

            Assert.AreEqual(true, result.AdditionalValues[AdditionalValuesKeys.SortDescending]);
        }

        [TestMethod]
        public void StringLength_correctly_mapped()
        {
            Type input = typeof(TestModel);
            var mp = new ExtendedDataAnnotationsModelMetadataProvider();
            var expected = 123;

            var result = mp.GetMetadataForType(null, input);

            var noStringLength = result.Properties.Single(p => p.PropertyName == "DoesNotHaveStringLength");
            var hasStringLength = result.Properties.Single(p => p.PropertyName == "HasStringLength");

            Assert.IsFalse(noStringLength.AdditionalValues.ContainsKey(AdditionalValuesKeys.MaximumStringLength));
            Assert.AreEqual(expected, hasStringLength.AdditionalValues[AdditionalValuesKeys.MaximumStringLength]);
        }

        [TestMethod]
        public void WatermarkPrompt_correctly_mapped()
        {
            Type input = typeof(TestModel);
            var mp = new ExtendedDataAnnotationsModelMetadataProvider();

            var result = mp.GetMetadataForType(null, input);

            var noPrompt = result.Properties.Single(p => p.PropertyName == "DoesNotHavePrompt");
            var hasPrompt = result.Properties.Single(p => p.PropertyName == "HasPrompt");

            Assert.IsTrue(string.IsNullOrEmpty(noPrompt.Watermark));
            Assert.AreEqual("Sam", hasPrompt.Watermark);
        }

        [TestMethod]
        public void DisplayOrder_has_correct_order()
        {
            Type input = typeof(TestModel);
            var mp = new ExtendedDataAnnotationsModelMetadataProvider();

            var result = mp.GetMetadataForType(null, input);

            // Does our 'order me' property have the dipaly order additional value?
            var orderMe1 = result.Properties.Single(p => p.PropertyName == "OrderMe1");
            Assert.IsTrue(orderMe1.AdditionalValues.ContainsKey(AdditionalValuesKeys.DisplayOrder));

            // Are the properties sorted correctly?
            var orderMeResult = result.Properties.Where(p => p.PropertyName.Contains("OrderMe"));
            Assert.AreEqual("OrderMe1", orderMeResult.ElementAt(0).PropertyName);
            Assert.AreEqual("OrderMe2", orderMeResult.ElementAt(1).PropertyName);
            Assert.AreEqual("OrderMe3", orderMeResult.ElementAt(2).PropertyName);
        }

        [DisplayColumn(null, "SortMe")]
        private class TestModel
        {
            [Display]
            public int DoesNotHaveAutoGenerateFilter { get; set; }
            [Display(AutoGenerateFilter = false)]
            public int HasAutoGenerateFilterFalse { get; set; }
            [Display(AutoGenerateFilter = true)]
            public int HasAutoGenerateFilterTrue { get; set; }
            [Display]
            public int DoesNotHaveGroupName { get; set; }
            [Display(GroupName = "Bob")]
            public int HasGroupName { get; set; }
            [Display]
            public int DoesNotHavePrompt { get; set; }
            [Display(Prompt = "Sam")]
            public int HasPrompt { get; set; }
            public int DoesNotHaveStringLength { get; set; }
            [StringLength(123)]
            public int HasStringLength { get; set; }
            public int SortMe { get; set; }

            [Display(Order=1)]
            public int OrderMe1 { get; set; }
            [Display(Order = 3)]
            public int OrderMe3 { get; set; }
            [Display(Order = 2)]
            public int OrderMe2 { get; set; }
        }

        [DisplayColumn(null, "SortMe", true)]
        private class TestModelSortDescending
        {
            public int SortMe { get; set; }
        }
    }
}
